package com;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.io.FileOutputStream;
import java.util.*;
import java.util.List;

public class PDFExporter {
    private static final float ROW_HEIGHT = 24; // 行高20单位

    private static BaseFont chineseBaseFont;   // 黑体（用于加粗）
    private static BaseFont chineseSongFont;

    static {
        try {
            // 加载黑体（加粗）
            chineseBaseFont = BaseFont.createFont(
                    "C:/WINDOWS/FONTS/SIMHEI.TTF",
                    BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED
            );

            // 加载宋体（常规）
            chineseSongFont = BaseFont.createFont(
                    "C:/WINDOWS/FONTS/SIMSUN.TTC,1",
                    BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED
            );
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("无法加载中文字体: " + e.getMessage());
        }
    }

    public static void exportToPDF(DefaultTableModel model, List<String> columns, List<Integer> widthRatios,
                                   String filePath, String headerType,
                                   String headerLeft, String headerCenter, String headerRight,
                                   String groupColumn, boolean addSerialColumn,
                                   int headerFontSize, boolean headerBold,
                                   int bodyFontSize, boolean bodyBold,
                                   int titleFontSize, boolean titleBold,
                                   int subtitleFontSize, boolean subtitleBold,
                                   boolean fillBlankRows,
                                   float rowHeightFactor,
                                   String serialColName,   // 新增：序号列名
                                   int serialWidth) {
        try {
            // 根据抬头类型设置不同的页边距（单位：厘米）
            float marginLeft, marginRight, marginTop, marginBottom;

            // 转换为点（1厘米=28.35点）
            if ("卷内文件目录".equals(headerType)) {
                marginLeft = 2.5f * 28.35f;
                marginRight = 2.0f * 28.35f;
                marginTop = 80;
                marginBottom = 1.5f * 28.35f;
            } else if ("盒内文件目录".equals(headerType)) {
                marginLeft = 1.0f * 28.35f;
                marginRight = 1.0f * 28.35f;
                marginTop = 80;
                marginBottom = 1.0f * 28.35f;
            } else {
                marginLeft = marginRight = marginTop = marginBottom = 36;
            }

            Document document = new Document(PageSize.A4, marginLeft, marginRight, marginTop, marginBottom);
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePath));


            document.open();

            HeaderFooterPageEvent event = new HeaderFooterPageEvent();
            // 传递标题字体设置给页眉事件
            event.setTitleFont(titleFontSize, titleBold);
            writer.setPageEvent(event);

            event.setSubtitleFont(subtitleFontSize, subtitleBold); // 设置副标题字体
            // 获取分组数据 - 使用原始模型列名
            Map<String, List<Vector<Object>>> groupedData = groupData(model, groupColumn);

            int groupCount = 0;
            float[] columnWidths;

            for (Map.Entry<String, List<Vector<Object>>> entry : groupedData.entrySet()) {
                groupCount++;
                if (groupCount > 1) {
                    document.newPage();
                }

                Vector<Object> firstRow = entry.getValue().get(0);
                event.setHeaderInfo(
                        headerType,
                        headerLeft, headerCenter, headerRight,
                        getValueFromRow(firstRow, headerLeft, model),
                        getValueFromRow(firstRow, headerCenter, model),
                        getValueFromRow(firstRow, headerRight, model),
                        entry.getKey()
                );


                if (addSerialColumn) {
                    List<Integer> newWidthRatios = new ArrayList<>();
                    newWidthRatios.add(serialWidth); // 使用传入的宽度比例
                    newWidthRatios.addAll(widthRatios);
                    columnWidths = calculateColumnWidths(newWidthRatios);
                } else {
                    columnWidths = calculateColumnWidths(widthRatios);
                }

                // 创建表格（使用预先计算的列宽比例）
                PdfPTable table = createTable(columns, columnWidths, entry.getValue(), model,
                        addSerialColumn, groupColumn,
                        headerFontSize, headerBold,
                        bodyFontSize, bodyBold, headerType,
                        serialColName);
                document.add(table);



                if (fillBlankRows) {
                    float tableEndY = writer.getVerticalPosition(false);
                    float pageBottom = document.bottom();
                    float spaceNeeded = tableEndY - pageBottom;


                    if (spaceNeeded > 0) {
                        // 使用固定的行高20单位（ROW_HEIGHT）来计算
                        float blankRowHeight = ROW_HEIGHT * rowHeightFactor;
                        // 计算空白行数量
                        int blankRows = (int) (spaceNeeded / blankRowHeight);

                        if (blankRows > 0) {
                            // 添加自适应空白行（使用固定的行高）
                            addAdaptiveBlankRows(writer, document, blankRows,
                                    ROW_HEIGHT, rowHeightFactor, tableEndY, columnWidths);
                        }
                    }
                }
            }
            document.close();

            JOptionPane.showMessageDialog(null,
                    "PDF导出成功!\n保存位置: " + filePath,
                    "导出成功", JOptionPane.INFORMATION_MESSAGE);

        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null,
                    "导出PDF时出错: " + e.getMessage(),
                    "导出失败", JOptionPane.ERROR_MESSAGE);
        }
    }

    // 计算实际行高（基于表格最后一行）
    private static float calculateActualRowHeight(PdfPTable table) {
        if (table.getRows().size() > 0) {
            PdfPRow lastRow = table.getRow(table.getRows().size() - 1);
            return lastRow.getMaxHeights();
        }
        return ROW_HEIGHT; // 默认行高
    }
    private static void addAdaptiveBlankRows(PdfWriter writer, Document document,
                                             int blankRows, float baseRowHeight,
                                             float rowHeightFactor, float startY,
                                             float[] columnWidths)
            throws DocumentException {

        // 计算实际行高 = 基础行高 * 倍数
        float actualRowHeight = baseRowHeight * rowHeightFactor;

        PdfPTable blankTable = new PdfPTable(columnWidths);
        blankTable.setWidthPercentage(100);

        for (int i = 0; i < blankRows; i++) {
            for (int j = 0; j < columnWidths.length; j++) {
                PdfPCell blankCell = new PdfPCell(new Phrase(" "));
                blankCell.setFixedHeight(actualRowHeight); // 使用计算后的行高
                blankCell.setBorder(Rectangle.NO_BORDER);
                blankCell.setPadding(5);
                blankTable.addCell(blankCell);
            }
        }

        document.add(blankTable);
        drawGridLines(writer, document, blankRows, actualRowHeight, startY, columnWidths);
    }

    // 修改后的网格线绘制方法（使用指定的起始Y坐标）
    private static void drawGridLines(PdfWriter writer, Document document,
                                      int blankRows, float rowHeight,
                                      float startY, float[] columnWidths) {
        try {
            // 计算结束Y坐标
            float endY = startY - (blankRows * rowHeight);

            // 获取页面边界
            float leftX = document.left();
            float rightX = document.right();

            // 计算列宽总和
            float totalWidth = 0;
            for (float width : columnWidths) {
                totalWidth += width;
            }

            // 计算每列的实际位置
            float currentX = leftX;
            List<Float> columnPositions = new ArrayList<>();
            columnPositions.add(leftX);

            for (float width : columnWidths) {
                float columnWidth = (width / totalWidth) * (rightX - leftX);
                currentX += columnWidth;
                columnPositions.add(currentX);
            }

            PdfContentByte canvas = writer.getDirectContent();
            canvas.saveState();
            canvas.setLineWidth(0.5f);
            canvas.setLineCap(PdfContentByte.LINE_CAP_PROJECTING_SQUARE);

            // 绘制垂直线
            for (float x : columnPositions) {
                canvas.moveTo(x, startY);
                canvas.lineTo(x, endY);
            }

            // 绘制水平线
            for (int i = 0; i <= blankRows; i++) {
                float y = startY - (i * rowHeight);
                canvas.moveTo(leftX, y);
                canvas.lineTo(rightX, y);
            }

            canvas.stroke();
            canvas.restoreState();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    static class HeaderFooterPageEvent extends PdfPageEventHelper {
        private String headerType;
        private String headerLeft;
        private String headerCenter;
        private String headerRight;
        private String leftValue;
        private String centerValue;
        private String rightValue;
        private String groupKey;
        private int titleFontSize = 16;
        private boolean titleBold = true;
        private int subtitleFontSize = 9;
        private boolean subtitleBold = false;

        public void setSubtitleFont(int fontSize, boolean isBold) {
            this.subtitleFontSize = fontSize;
            this.subtitleBold = isBold;
        }
        public void setTitleFont(int fontSize, boolean isBold) {
            this.titleFontSize = fontSize;
            this.titleBold = isBold;
        }
        public void setHeaderInfo(String headerType,
                                  String headerLeft, String headerCenter, String headerRight,
                                  String leftValue, String centerValue, String rightValue,
                                  String groupKey) {
            this.headerType = headerType;
            this.headerLeft = headerLeft;
            this.headerCenter = headerCenter;
            this.headerRight = headerRight;
            this.leftValue = leftValue;
            this.centerValue = centerValue;
            this.rightValue = rightValue;
            this.groupKey = groupKey;
        }

        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            try {
                PdfContentByte cb = writer.getDirectContent();
                cb.saveState();

                // 设置页眉位置：从页面顶部开始
                float pageTop = writer.getPageSize().getTop();
                float startY = pageTop - 42; // 从页面顶部向下20单位

                // 1. 添加抬头类型（居中）
                cb.beginText();
                // 根据是否加粗选择字体
                BaseFont titleFont = titleBold ? chineseBaseFont : chineseSongFont;
                cb.setFontAndSize(titleFont, titleFontSize);
                cb.showTextAligned(
                        Element.ALIGN_CENTER,
                        headerType,
                        (document.left() + document.right()) / 2,
                        startY,
                        0
                );
                cb.endText();

                // 副标题（页眉中的左中右列名）

                // 2. 添加三列信息（左、中、右）
                float columnsY = startY - 30;
                cb.beginText();


                // 使用副标题字体设置
                BaseFont subtitleFont = subtitleBold ? chineseBaseFont : chineseSongFont;
                cb.setFontAndSize(subtitleFont, subtitleFontSize);
                // 修改点1：仅当列名非空时才显示
                if (headerCenter != null && !headerCenter.isEmpty()) {
                    cb.showTextAligned(
                            Element.ALIGN_CENTER,
                            headerCenter + ": " + centerValue,
                            (document.left() + document.right()) / 2,
                            columnsY,
                            0
                    );
                }

                if (headerLeft != null && !headerLeft.isEmpty()) {
                    cb.showTextAligned(
                            Element.ALIGN_LEFT,
                            headerLeft + ": " + leftValue,
                            document.left(),
                            columnsY,
                            0
                    );
                }

                if (headerRight != null && !headerRight.isEmpty()) {
                    cb.showTextAligned(
                            Element.ALIGN_RIGHT,
                            headerRight + ": " + rightValue,
                            document.right(),
                            columnsY,
                            0
                    );
                }

                cb.endText();

                cb.restoreState();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static PdfPTable createTable(List<String> columns, float[] columnWidths,
                                         List<Vector<Object>> dataRows, DefaultTableModel model,
                                         boolean addSerialColumn, String groupColumn,
                                         int headerFontSize, boolean headerBold,
                                         int bodyFontSize, boolean bodyBold,
                                         String headerType,
                                         String serialColName){

        List<String> filteredColumns = new ArrayList<>();
        for (String column : columns) {
            if (!(addSerialColumn && serialColName.equals(column))) {
                filteredColumns.add(column);
            }
        }

        // 创建表格（使用传入的列宽比例）
        PdfPTable table = new PdfPTable(columnWidths);
        table.setWidthPercentage(100);
        table.setSpacingBefore(0);
        table.setSpacingAfter(0);

        // 添加表头
        Font headerFont = new Font(chineseBaseFont, headerFontSize,
                headerBold ? Font.BOLD : Font.NORMAL);

        // 添加序号列表头单元格 - 使用传入的自定义名称
        if (addSerialColumn) {
            String serialHeaderText = (serialColName != null && !serialColName.isEmpty()) ?
                    serialColName :
                    ("卷内文件目录".equals(headerType) ? "序号" : "件号");

            PdfPCell serialHeaderCell = new PdfPCell(new Phrase(serialHeaderText, headerFont));
            serialHeaderCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            serialHeaderCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            serialHeaderCell.setPadding(5);
            serialHeaderCell.setBorder(Rectangle.BOX);
            table.addCell(serialHeaderCell);
        }

        for (String column : filteredColumns) {
            PdfPCell headerCell = new PdfPCell(new Phrase(column, headerFont));
            headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            headerCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            headerCell.setPadding(5);
            headerCell.setBorder(Rectangle.BOX);
            table.addCell(headerCell);
        }


        table.setHeaderRows(1);

        // 创建列名到索引的映射
        Map<String, Integer> columnIndexMap = new HashMap<>();
        for (int i = 0; i < model.getColumnCount(); i++) {
            columnIndexMap.put(model.getColumnName(i), i);
        }

        // 添加数据行
        Font dataFont = new Font(chineseBaseFont, bodyFontSize,
                bodyBold ? Font.BOLD : Font.NORMAL);
        int serialNumber = 1; // 每组数据序号从1开始

        for (Vector<Object> row : dataRows) {
            // 添加序号列数据
            if (addSerialColumn) {
                PdfPCell serialCell = new PdfPCell(new Phrase(String.valueOf(serialNumber++), dataFont));
                serialCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                serialCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                serialCell.setPadding(5);
                serialCell.setBorder(Rectangle.BOX);
                table.addCell(serialCell);
            }

            // 添加其他列数据（使用过滤后的列名）
            for (String column : filteredColumns) {
                Integer colIndex = columnIndexMap.get(column);
                String cellValue = "";

                if (colIndex != null && colIndex < row.size()) {
                    Object value = row.get(colIndex);
                    cellValue = (value != null) ? value.toString() : "";
                }

                PdfPCell cell = new PdfPCell(new Phrase(cellValue, dataFont));
                cell.setHorizontalAlignment(isLeftAlignedColumn(column) ?
                        Element.ALIGN_LEFT : Element.ALIGN_CENTER);
                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                cell.setPadding(5);
                cell.setUseAscender(true);
                cell.setUseDescender(true);
                cell.setLeading(0, 1.2f);
                cell.setBorder(Rectangle.BOX);
                table.addCell(cell);
            }
        }

        return table;
    }

    // 判断列是否需要居左
    private static boolean isLeftAlignedColumn(String columnName) {
        // 以下列名居左，其余居中
        return "档号".equals(columnName) ||
                "文件编号".equals(columnName) ||
                "责任者".equals(columnName) ||
                "题名".equals(columnName) ||
                "文件题名".equals(columnName);
    }

    // 自定义单元格事件，用于精确控制边框
    static class CellMarginEvent implements PdfPCellEvent {
        private final Set<Float> xCoordinates = new HashSet<>();
        private final Set<Float> cellHeights = new HashSet<>();
        private float left = Float.MAX_VALUE;
        private float right = Float.MIN_VALUE;

        @Override
        public void cellLayout(PdfPCell cell, Rectangle rect, PdfContentByte[] canvases) {
            this.xCoordinates.add(rect.getLeft());
            this.xCoordinates.add(rect.getRight());
            this.cellHeights.add(rect.getHeight());

            left = Math.min(left, rect.getLeft());
            right = Math.max(right, rect.getRight());
        }

        public Set<Float> getXCoordinates() {
            return xCoordinates;
        }

        public Set<Float> getCellHeights() {
            return cellHeights;
        }

        public float getLeft() {
            return left;
        }

        public float getRight() {
            return right;
        }
    }

    private static void addBlankRows(PdfWriter writer, Document document,
                                     PdfPTable table, int columnsCount, int blankRows)
            throws DocumentException {
        // 获取当前垂直位置（表格结束位置）
        float topY = writer.getVerticalPosition(false);

        // 添加空白行
        for (int i = 0; i < blankRows; i++) {
            for (int j = 0; j < columnsCount; j++) {
                PdfPCell blankCell = new PdfPCell(new Phrase(" "));
                blankCell.setFixedHeight(ROW_HEIGHT);
                blankCell.setBorder(Rectangle.NO_BORDER); // 禁用默认边框
                table.addCell(blankCell);
            }
        }

        // 绘制网格线（使用新的方法）
        drawGridLines(writer, document, table, topY, blankRows);
    }

    private static void drawGridLines(PdfWriter writer, Document document,
                                      PdfPTable table, float startY, int blankRows) {
        // 获取表格边界
        float tableLeft = document.left();
        float tableRight = document.right();

        // 计算列位置
        float[] columnPositions = new float[table.getNumberOfColumns() + 1];
        float currentX = tableLeft;
        float totalWidth = tableRight - tableLeft;

        for (int i = 0; i < table.getNumberOfColumns(); i++) {
            columnPositions[i] = currentX;
            currentX += (table.getAbsoluteWidths()[i] / table.getTotalWidth()) * totalWidth;
        }
        columnPositions[table.getNumberOfColumns()] = tableRight;

        // 绘制网格线
        PdfContentByte canvas = writer.getDirectContent();
        canvas.saveState();
        canvas.setLineWidth(0.5f);

        // 绘制垂直线
        for (float x : columnPositions) {
            canvas.moveTo(x, startY);
            canvas.lineTo(x, startY - (blankRows * ROW_HEIGHT));
        }

        // 绘制水平线
        float currentY = startY;
        for (int i = 0; i <= blankRows; i++) {
            canvas.moveTo(tableLeft, currentY);
            canvas.lineTo(tableRight, currentY);
            currentY -= ROW_HEIGHT;
        }

        canvas.stroke();
        canvas.restoreState();
    }

    // 辅助方法：从行中获取值（使用实际Excel值）
    private static String getValueFromRow(Vector<Object> row, String columnName, DefaultTableModel model) {
        if (columnName == null || columnName.isEmpty()) return "";

        // 查找列索引
        int columnIndex = -1;

        // 先在模型列名中查找
        for (int i = 0; i < model.getColumnCount(); i++) {
            if (columnName.equals(model.getColumnName(i))) {
                columnIndex = i;
                break;
            }
        }

        // 获取实际值
        if (columnIndex >= 0 && columnIndex < row.size()) {
            Object value = row.get(columnIndex);
            return (value != null) ? value.toString() : "";
        }

        return "";
    }

    // 辅助方法：数据分组（关键修改）
    private static Map<String, List<Vector<Object>>> groupData(DefaultTableModel model, String groupColumn) {
        Map<String, List<Vector<Object>>> groupedData = new LinkedHashMap<>();

        // 获取列索引 - 使用更健壮的匹配方式
        int groupColumnIndex = -1;
        if (groupColumn != null && !groupColumn.isEmpty()) {
            // 标准化分组列名：去除首尾空格 + 转为小写
            String normalizedGroupColumn = groupColumn.trim().toLowerCase();

            for (int i = 0; i < model.getColumnCount(); i++) {
                // 标准化模型列名
                String modelCol = model.getColumnName(i).trim().toLowerCase();

                if (normalizedGroupColumn.equals(modelCol)) {
                    groupColumnIndex = i;
                    break;
                }
            }
        }

        // 分组数据
        for (int i = 0; i < model.getRowCount(); i++) {
            Vector<Object> row = new Vector<>();
            for (int j = 0; j < model.getColumnCount(); j++) {
                row.add(model.getValueAt(i, j));
            }

            String groupKey = "所有数据";
            if (groupColumnIndex >= 0 && groupColumnIndex < row.size()) {
                Object value = row.get(groupColumnIndex);
                // 处理空值情况
                groupKey = (value != null && !value.toString().isEmpty()) ?
                        value.toString() : "未分组";
            }

            if (!groupedData.containsKey(groupKey)) {
                groupedData.put(groupKey, new ArrayList<>());
            }
            groupedData.get(groupKey).add(row);
        }
        return groupedData;
    }

    // 计算列宽（添加序号列处理）
    private static float[] calculateColumnWidths(List<Integer> widthRatios, boolean addSerialColumn) {
        if (addSerialColumn) {
            List<Integer> newRatios = new ArrayList<>();
            newRatios.add(5); // 序号列宽度比例
            newRatios.addAll(widthRatios);
            return calculateColumnWidths(newRatios);
        } else {
            return calculateColumnWidths(widthRatios);
        }
    }

    // 计算列宽（基础方法）
    private static float[] calculateColumnWidths(List<Integer> widthRatios) {
        float totalRatio = 0;
        for (Integer ratio : widthRatios) {
            totalRatio += ratio;
        }

        float[] columnWidths = new float[widthRatios.size()];
        for (int i = 0; i < widthRatios.size(); i++) {
            columnWidths[i] = (widthRatios.get(i) / totalRatio) * 100;
        }
        return columnWidths;
    }
}